#include "SocketAcceptor.h"

SocketAcceptor::SocketAcceptor(InetAddress &addr)
  : debug_(false)
{
  this->open(addr);
}

SocketAcceptor::~SocketAcceptor()
{
  close( handle_ );
}

Socket SocketAcceptor::getHandle() const
{
  return handle_;
}

void SocketAcceptor::open(const InetAddress &addr)
{
  addrinfo hints;
  addrinfo *lookups;

  memset(&hints, 0, sizeof hints);

  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  if (getaddrinfo(NULL, addr.getPort().c_str(), &hints, &lookups) != 0 )
    std::cout << "Couldnt get addrinfo";
  
  addrinfo * p;
  for (p = lookups; p != NULL; p = p->ai_next)
    {
      if (debug_) std::cout << "Trying new addrinfo struct\n";
      
      if (p->ai_family != AF_INET)
	{
	  if (debug_) std::cout << "Addrinfo isnt ipv4\n";
	  continue;
	}

      if ( (handle_ = socket(p->ai_family, p->ai_socktype, p->ai_protocol )) == -1 )
	{
	  if (debug_) std::cout << "Socket failed\n";
	  continue;
	}

      int yes = 1;
      if ( setsockopt( handle_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes ) == -1 )
	{
	  if (debug_) std::cout << "setsockopt failed\n";
	  continue;
	}
       
      if ( bind( handle_, p->ai_addr, p->ai_addrlen) == -1 )
	{
	  if (debug_) std::cout << "bind failed\n";
	  close( handle_ );
	  continue;
	}

      if (debug_) std::cout << "Found addrinfo\n";

      break;
    }

  if (p == NULL && debug_)
    std::cout << "Failed to find addrinfo\n";
    

  freeaddrinfo(lookups);

  if ( listen(handle_, 10) == -1 )
    {
      if (debug_) std::cout << "listen failed\n";
      close( handle_ ); //maybe dont close??
    }

  if (debug_) std::cout << "Ready for connections!!\n";
}

void SocketAcceptor::accept(SocketStream &ss)
{
  ss.setHandle( ::accept(handle_, 0, 0 ));
}



